import { defineStore } from "pinia";
import { pinia } from "..";
import { GlobalStoreEnum } from "../enum";
import { IMenu, IMenuState, Tags } from "../interface";
import { getHash } from "../util/store.util";
import { useAclHooks } from "./acl.store";
const acl = useAclHooks();
const deepLeaf = (item: IMenu[]) => {
  const leafs = [] as IMenu[];
  if (item?.length) {
    item.forEach(i => {
      if (i.isLeaf) {
        leafs.push(i);
      }
      if (i?.children?.length) {
        leafs.push(...deepLeaf(i?.children));
      }
    });
  }
  return leafs;
};
const deepActive = (item: IMenu[]) => {
  if (item?.length) {
    const leaf = item.find(
      i => i.isLeaf && acl.hasMenuAcl("get", acl.getRouter(i))
    );
    if (leaf) {
      return leaf;
    }
    if (item[0]?.children.length) {
      return deepActive(item[0].children);
    }
  }
  return {};
};
const deepActiveByLink = (parent: IMenu, item: IMenu[], router: string) => {
  if (item?.length) {
    const pre = parent;
    if (router) {
      for (const i of item) {
        if (i.moda !== "LINK") {
          if (i.router === router && i.isLeaf) {
            return { pre: pre ?? i, i, find: true };
          }
          if (i.children?.length) {
            const { children, ...args } = i;
            const { find, i: p } = deepActiveByLink(
              args as IMenu,
              children,
              router
            );
            if (find) {
              return { pre: args, i: p, find: true };
            }
          }
        }
      }
    }
    const activeHorizontal = item.find(
      r =>
        r.parentId === null &&
        r.moda !== "LINK" &&
        acl.hasMenuAcl("get", acl.getRouter(r))
    );
    return {
      pre: activeHorizontal,
      i: activeHorizontal?.isLeaf
        ? activeHorizontal
        : deepActive(activeHorizontal?.children),
      find: false
    };
  }
  return {};
};

export const useMenu = defineStore(GlobalStoreEnum.MENU, {
  state: (): IMenuState => ({
    menu: [],
    active: {} as IMenu,
    activeHorizontal: {} as IMenu,
    cacheTags: [] as Tags[]
  }),

  getters: {
    menus(state) {
      return state.menu;
    },
    flatMenus(state) {
      return deepLeaf(state.menu);
    },
    parentMenu(state) {
      return state.menu.filter(m => !m.parentId);
    },
    getDefaultActive() {
      return (this.active || {}) as IMenu;
    },
    getActiveHorizontal() {
      return this.activeHorizontal;
    },
    getCacheTags() {
      return (this.cacheTags as Tags[]) || [];
    },
    getActiveCacheTags() {
      return (this.cacheTags as Tags[]).find(r => r.active) || ({} as Tags);
    }
  },

  actions: {
    setMenu(menu: IMenu[]) {
      this.initMenu();
      this.menu = menu;
      if (this.menu?.length) {
        this.setActiveByLink();
      }
    },

    isHasChildren(item: IMenu) {
      let noHas = true;
      const hasChild = (childs: IMenu[]) => {
        for (const c of childs) {
          if (c.isLeaf && acl.hasMenuAcl("get", acl.getRouter(c))) {
            noHas = false;
            break;
          }
          if (c.children && c.children.length) {
            hasChild(c.children);
          }
        }
      };
      if (item.children && item.children.length) {
        hasChild(item.children);
      }
      return !noHas;
    },

    setActiveByLink(parent = null) {
      let path = getHash(true);
      if (!path || !acl.hasMenuAcl("get", path)) {
        path = acl.getAclPath();
      }
      this.setActivate(parent, path);
      this.cacheTags.push({
        id: this.active.id,
        text: this.active.text,
        router: this.active.router,
        moda: this.active.moda,
        frame: this.active.frame,
        link: this.active.link,
        active: true
      });
    },

    setActivate(parent: IMenu, path: string) {
      const { pre, i } = deepActiveByLink(parent, this.menu, path);
      this.active = i;
      this.activeHorizontal = pre;
    },

    getParentMenuById(id: string) {
      const parent = this.menu.find((m: IMenu) => m.id === id);
      return parent?.children || [];
    },

    setChoose(id: string) {
      this.activeHorizontal = (this.parentMenu as IMenu[]).find(
        r => r.id === id
      );
      this.active = deepActive(this.activeHorizontal.children);
      if (!this.active.id) {
        this.active = this.activeHorizontal;
      }
      this.setCacheTags(this.active);
    },

    changeCacheTags(tags: Tags) {
      if (!tags.active) {
        const activeData = (this.cacheTags as Tags[]).find(r => r.active);
        if (activeData) {
          activeData.active = false;
        }
        tags.active = true;
        this.setActivate(null, tags.router);
      }
    },

    setCacheTags(data: IMenu) {
      const has = (this.cacheTags as Tags[]).find(r => r.id === data.id);
      const activeData = (this.cacheTags as Tags[]).find(r => r.active);
      if (activeData) {
        activeData.active = false;
      }
      if (!has) {
        this.cacheTags.push({
          id: data.id,
          text: data.text,
          router: data.router,
          active: true,
          moda: data.moda,
          frame: data.frame,
          link: data.link
        });
      } else {
        has.active = true;
      }
      this.setActivate(null, data.router);
    },

    delCacheTags(id: string, sign: number) {
      const len = (this.cacheTags as Tags[]).length;
      const has = (this.cacheTags as Tags[]).findIndex(r => r.id === id);
      let reset = false;
      if (has > -1) {
        switch (sign) {
          case 1:
            // 关闭自己标签页
            if (this.cacheTags[has].active) {
              let index = has - 1;
              if (has === 0 && len > 1) {
                index = has + 1;
              }
              const tags = this.cacheTags[index] as Tags;
              tags.active = true;
              this.setActivate(null, tags.router);
              reset = true;
            }
            (this.cacheTags as Tags[]).splice(has, 1);
            break;
          case 2:
            // 关闭左侧标签页
            // eslint-disable-next-line no-case-declarations
            const left = (this.cacheTags as Tags[]).filter((_r, i) => i < has);
            if (left.find(r => r.active)) {
              this.cacheTags[has].active = true;
              reset = true;
              this.setActivate(null, this.cacheTags[has].router);
            }
            (this.cacheTags as Tags[]).splice(0, has);
            break;
          case 3:
            // 关闭右侧标签页
            // eslint-disable-next-line no-case-declarations
            const right = (this.cacheTags as Tags[]).filter((_r, i) => i > has);

            if (right.find(r => r.active)) {
              this.cacheTags[has].active = true;
              reset = true;
              this.setActivate(null, this.cacheTags[has].router);
            }
            (this.cacheTags as Tags[]).splice(has + 1, right.length);
            break;
          case 4:
            // 关闭其他标签页
            if (!this.cacheTags[has].active) {
              this.cacheTags[has].active = true;
              reset = true;
              this.setActivate(null, this.cacheTags[has].router);
            }
            this.cacheTags = [this.cacheTags[has]];
            break;
          case 5:
            // 关闭所有
            this.cacheTags = [];
        }
      }
      return reset;
    },

    getTreeTextArray(menus: IMenu[]) {
      const arr = [] as IMenu[];
      let ok = false;
      menus.forEach(m => {
        if (m.isLeaf && m.router === this.getDefaultActive.router) {
          arr.push(m);
          ok = true;
        }
        if (m?.children?.length) {
          const { ok, arr: a } = this.getTreeTextArray(m.children);
          if (ok) {
            arr.push(m, ...a);
          }
        }
      });
      return { arr, ok };
    },

    initMenu() {
      this.menu = [];
      this.active = {} as IMenu;
      this.activeHorizontal = {} as IMenu;
      this.cacheTags = [] as Tags[];
    }
  }
});

export const useMenuHooks = () => {
  return useMenu(pinia);
};
